﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace HaSdkWrapper
{
    internal static class Helper
    {
        public static void Fill(this byte[] arr, byte b)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                arr[i] = b;
            }
        }
    }

    public class HaSdkConstants
    {

        /// MAX_LANE_NUM -> (4)
        public const int MAX_LANE_NUM = 4;

        /// MAX_FLASH_NUM -> (4)
        public const int MAX_FLASH_NUM = 4;

        /// MAX_RADAR_NUM -> (4)
        public const int MAX_RADAR_NUM = 4;

        /// MAX_INPUT_IO_NUM -> (8)
        public const int MAX_INPUT_IO_NUM = 8;

        /// MAX_COIL_GROUP -> (4)
        public const int MAX_COIL_GROUP = 4;

        /// ERR_NONE -> 0
        public const int ERR_NONE = 0;

        /// ERR_INVALID_PARAM -> -1
        public const int ERR_INVALID_PARAM = -1;

        /// ERR_TIMEOUT -> -2
        public const int ERR_TIMEOUT = -2;

        /// ERR_SEND_BUF_FULL -> -3
        public const int ERR_SEND_BUF_FULL = -3;

        /// ERR_SYS_NOT_MATCH -> -4
        public const int ERR_SYS_NOT_MATCH = -4;

        /// ERR_UNCONNECTED -> -5
        public const int ERR_UNCONNECTED = -5;


        public const int MESSAGE_ID_REBOOT = 0;	/* 重启机器 */
        public const int MESSAGE_ID_RESTART = 1;		/* 重启进程 */
        public const int MESSAGE_ID_HEART_BEAT = 2;		/* 心跳包 */
        public const int MESSAGE_ID_SYNCTIME = 3;		/* 时间同步请求 */
        public const int MESSAGE_ID_REPLY = 4;		/* 统一应答 */
        public const int MESSAGE_ID_CAR = 5;		/* 抓拍数据包 */
        public const int MESSAGE_ID_FLOWCOUNT = 6;		/* 流量统计包 */
        public const int MESSAGE_ID_WORK_STATE = 7;      /* 系统状态包 */

        public const int MESSAGE_ID_SERIAL_READ = 8;       /* 透明串口 - 读 */
        public const int MESSAGE_ID_SERIAL_WRITE = 9;      /* 透明串口 - 写 */

        public const int MESSAGE_ID_REQ_AUTH = 101;	/* 查询授权 */
        public const int MESSAGE_ID_SET_AUTH = 102;	/* 提交授权码 */
        public const int MESSAGE_ID_LIVE_IMAGE = 103; /* 实时图像 */
    }


    #region struct definition

    [StructLayout(LayoutKind.Sequential)]
    public struct config_size
    {

        /// unsigned short
        public ushort width;

        /// unsigned short
        public ushort height;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct config_rect
    {

        /// unsigned short
        public ushort x;

        /// unsigned short
        public ushort y;

        /// unsigned short
        public ushort w;

        /// unsigned short
        public ushort h;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct config_point
    {

        /// unsigned short
        public ushort x;

        /// unsigned short
        public ushort y;

    }

    [StructLayout(LayoutKind.Sequential)]
    public struct config_worktime
    {

        /// unsigned char
        public byte start_hour;

        /// unsigned char
        public byte start_min;

        /// unsigned char
        public byte end_hour;

        /// unsigned char
        public byte end_min;
    }




    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_addr
    {

        /// char[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        public byte[] device_id;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        public byte[] device_name;


        /// char[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        public byte[] addr_id;

        /// char[96]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)]
        public byte[] addr_name;

        public string AddrName
        {
            set
            {
                var bytes = Encoding.UTF8.GetBytes(value);
                addr_name.Fill(0);
                bytes.CopyTo(addr_name, 0);

            }
            get { return Encoding.UTF8.GetString(addr_name).Replace("\0", ""); }
        }


        /// char[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        public byte[] direction_id;

        /// char[96]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)]
        public byte[] direction_name;

        /// unsigned short
        public ushort lane_number;

        /// unsigned short
        public ushort lane_start_id;

        /// unsigned char[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] match_light;

        /// char
        public byte master_mode;

        /// char
        public byte slave_mode;

        /// char
        public byte mode_change_threshold;

        /// unsigned char
        public byte serial_index;

        /// int
        public int serial_baudrate;

        /// unsigned char
        public byte serial_databit;

        /// unsigned char
        public byte serial_parity;

        /// unsigned char
        public byte serial_stopbit;

        /// char[113]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 113)]
        public byte[] resv;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct coil_io_attr
    {

        /// unsigned char
        public byte group;

        /// unsigned char
        public byte index;

        /// unsigned char
        public byte count;

        /// unsigned char
        public byte match_light;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_coil
    {

        /// int
        public int enable;

        /// unsigned int
        public uint distance;

        /// coil_io_attr[8]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.Struct)]
        public coil_io_attr[] io_attr;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public byte[] resv;
    }

    public enum RADAR_TYPE
    {

        /// RADAR_TYPE_NONE -> 0
        RADAR_TYPE_NONE = 0,

        /// RADAR_TYPE_CSRIN -> 1
        RADAR_TYPE_CSRIN = 1,

        /// RADAR_TYPE_CSRIN_M -> 2
        RADAR_TYPE_CSRIN_M = 2
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_radar
    {

        /// int
        public int enable;

        /// RADAR_TYPE
        public RADAR_TYPE type;

        /// unsigned int
        public uint count;

        /// unsigned char[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] match_lane;

        /// unsigned char[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] match_light;

        /// int
        public int enable_log;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public byte[] resv;
    }

    public enum vdetect_type
    {

        VDETECT_TYPE_RECO,

        VDETECT_TYPE_DET,

        VDETECT_TYPE_BOTH
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_vdetect
    {

        /// int
        public int enable;

        /// vdetect_type
        public vdetect_type type;

        /// int
        public int flash;

        /// int
        public int motion;

        /// int
        public int diff;

        /// config_rect
        public config_rect detect_area;

        /// config_rect
        public config_rect virtual_coil;

        /// int
        public int night_threshold;

        /// int
        public int rsv2;

        /// unsigned int
        public uint skip;

        /// unsigned int
        public uint cut;

        /// unsigned int
        public uint min_size;

        /// unsigned int
        public uint max_size;

        /// unsigned int
        public uint resize;

        /// float
        public float step;

        /// int
        public int debug;

        /// int
        public int draw_coil;

        /// int
        public int draw_area;

        public int resv0; //enum CALC_LANENO_METHOD m;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] match_light;


        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Struct)]
        public config_point[] virtual_coil_polygon;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
        public byte[] resv;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_face_detect
    {

        /// int
        public int enable;

        /// int
        public int debug;

        /// config_rect
        public config_rect detect_area;

        /// config_size
        public config_size minsize;

        /// config_size
        public config_size maxsize;

        /// float
        public float step;

        /// float
        public float ratio;

        /// unsigned int
        public uint interval;

        /// unsigned int
        public uint use_motion;

        /// unsigned int
        public uint face_step;

        /// char[48]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
        public byte[] resv;
    }

    public enum reco_filter_color
    {

        /// RECO_FILTER_BLUE -> 0
        RECO_FILTER_BLUE = 0,

        /// RECO_FILTER_BLACK -> 1
        RECO_FILTER_BLACK = 1,

        /// RECO_FILTER_YELLOW -> 2
        RECO_FILTER_YELLOW = 2,

        /// RECO_FILTER_WHITE -> 3
        RECO_FILTER_WHITE = 3,

        /// RECO_FILTER_GREEN -> 4
        RECO_FILTER_GREEN = 4
    }

    public enum reco_filter_num
    {

        /// RECO_FILTER_NULL -> 0
        RECO_FILTER_NULL = 0,

        /// RECO_FILTER_XUE -> 1
        RECO_FILTER_XUE = 1,

        /// RECO_FILTER_JING -> 2
        RECO_FILTER_JING = 2
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_reco
    {

        /// int
        public int enable;

        /// float
        public float ratio;

        /// char[16]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public byte[] province;

        /// unsigned short
        public ushort min_width;

        /// unsigned short
        public ushort max_width;

        /// config_rect[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Struct)]
        public config_rect[] reco_area;

        /// int
        public int draw_reco_area;

        /// unsigned int
        public uint filter_color;

        /// unsigned int
        public uint filter_num;

        /// unsigned short
        public ushort same_plate_report_time;

        /// unsigned char
        public byte draw_reco_area_video;

        public byte reco_mode;

        /// char[49]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
        public byte[] resv;
    }

    public enum PLATE_FILTER_TYPE
    {

        /// PLATE_FILTER_TYPE_NONE -> 0
        PLATE_FILTER_TYPE_NONE = 0
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_special
    {

        /// int
        public int merge_two;

        /// int
        public int keep_one;

        /// PLATE_FILTER_TYPE
        public PLATE_FILTER_TYPE plate_filter;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        public byte[] resv;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_limit_speed
    {

        /// unsigned short
        public ushort capture_count;

        /// unsigned short
        public ushort overspeed_count;

        /// unsigned int
        public uint interval;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] lspeed;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] rlspeed;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        public byte[] resv;
    }

    public enum UPLOAD_MODE
    {

        /// UPLOAD_MODE_TCP -> 0
        UPLOAD_MODE_TCP = 0,

        UPLOAD_MODE_FTP
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_net
    {

        /// UPLOAD_MODE
        public UPLOAD_MODE upload_mode;

        /// char[16]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string ftp_server;

        /// char[16]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string tcp_server;

        /// char[16]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string ntp_server;

        /// int
        public int ntp_interval;

        /// unsigned short
        public ushort ftp_port;

        /// unsigned short
        public ushort tcp_port;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string ftp_user;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string ftp_passwd;

        /// char[128]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
        public byte[] resv;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct CONF_OSD
    {

        /// unsigned short
        public ushort imgStartX;

        /// unsigned short
        public ushort imgStartY;

        /// unsigned char
        public byte imgFontSize;

        /// unsigned char[3]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
        public string imgFontColor;

        /// char[512]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
        public string imgOSDRules;

        /// char[16]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string resv;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct lamp_area
    {

        /// int
        public int lamp_num;

        /// unsigned short
        public ushort only_red_x;

        /// unsigned short
        public ushort only_red_y;

        /// unsigned short
        public ushort only_red_w;

        /// unsigned short
        public ushort only_red_h;

        /// unsigned short
        public ushort all_lamp_x;

        /// unsigned short
        public ushort all_lamp_y;

        /// unsigned short
        public ushort all_lamp_w;

        /// unsigned short
        public ushort all_lamp_h;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_people_red
    {

        /// int
        public int enable;

        /// lamp_area
        public lamp_area lamp;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public byte[] resv;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct config_gw_park
    {

        public byte offline; // 1为离线，0为在线, 2为自动（即脱机检查）
        public byte alarm_out_mode; //0为白名单开，1为过车开
        public byte transfer_offline_data; //上传离线数据
        public byte diable_serial_output;  //中断/恢复原本设备控制的串口输出，透明串口输出不在此控制

        public byte same_count; // 模糊匹配车牌阀值
        public byte min_volume; //最小音量
        public byte max_volume; //最大音量
        public byte cur_volume; //当前音量

        public byte light;

        public byte drive_direct; //0:全抓, 1:只抓车头，2只抓车尾

        public byte enable_smart_ctrl_light; //智能控灯使能
        public byte day_brightness; //白天亮度阀值

        public ushort alarmOutDuration; //自动开闸时间间隔(500-5000ms)

        public byte disable_io_port;  //中断GPIO控制
        public byte disable_io_output; //中断/恢复原本设备控制的继电器、电平输出

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
        public byte[] resv; //备用
    }




    [StructLayout(LayoutKind.Sequential)]
    public struct config_gateway
    {

        /// int
        public int magic_number;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_worktime
        public config_worktime worktime;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_addr
        public config_addr addr;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_reco
        public config_reco reco;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_limit_speed
        public config_limit_speed limit_speed;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_radar
        public config_radar radar;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_coil
        public config_coil coil;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_special
        public config_special special;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_net
        public config_net net;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_face_detect
        public config_face_detect face;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_vdetect
        public config_vdetect vdetect;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_people_red
        public config_people_red people_red;

        [MarshalAs(UnmanagedType.Struct)]
        /// config_gw_park
        public config_gw_park park;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct CONF_TEMP
    {

        /// char
        public byte enableLiveImage;

        /// char[124]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 124)]
        public string resv;

        /// char[128]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string authKey;

        /// char[256]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string authValue;

        /// int
        public int authResult;
    }

    public enum CAM_TYPE
    {

        CAM_TYPE_TI8127,

        CAM_TYPE_S2
    }

    public enum STREAM_FORMAT
    {

        /// STREAM_FORMAT_JPEG -> 1
        STREAM_FORMAT_JPEG = 1,

        /// STREAM_FORMAT_H264 -> 2
        STREAM_FORMAT_H264 = 2
    }

    public enum CHAR_ENCODE
    {

        /// CHAR_ENCODE_GBK -> 0
        CHAR_ENCODE_GBK = 0,

        CHAR_ENCODE_UTF8
    }

    public enum TRIG_TYPE
    {

        TRIG_TYPE_VIDEO,

        TRIG_TYPE_COIL,

        TRIG_TYPE_SOFT,

        TRIG_TYPE_RADIA
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct HA_LiveStream
    {

        /// int
        public int w;

        /// int
        public int h;

        /// STREAM_FORMAT
        public STREAM_FORMAT format;

        /// int
        public int streamLen;

        /// int
        public int streamBufSize;

        /// char*
        [MarshalAs(UnmanagedType.LPStr)]
        public string streamBuf;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct HA_AllowList
    {

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string plate;
        public ushort plateColor;
        public ushort year;           //记录的过期时间-年
        public ushort month;          //月
        public ushort day;            //日
        public byte hour;             //时
        public byte min;              //分
        public byte sec;              //秒
        [MarshalAs(UnmanagedType.I1)]
        public bool bEnable;          //记录是否有效标志

        public ushort enable_year;    //记录的生效时间-年
        public byte enable_month;     //月
        public byte enable_day;       //日
        public byte enable_hour;      //时
        public byte enable_min;       //分
        public byte enable_sec;       //秒

        [MarshalAs(UnmanagedType.I1)]
        public bool bAlarm;           //是否触发报警（黑名单记录）

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13, ArraySubType = UnmanagedType.I4)]
        public int[] resv;

        public override string ToString()
        {
            return
                $"号牌:{plate} 过期:{year:D4}-{month:D2}-{day:D2} 生效:{enable_year:D4}-{enable_month:D2}-{enable_day:D2} 黑名单:{bAlarm} 生效:{bEnable}";
        }
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct VERSION
    {

        /// char[64]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string protocl_version;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string arm_version;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string arm_buildtime;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string arm_code_version;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string dsp_version;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string dsp_buildtime;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string dsp_code_version;
    }


    [StructLayout(LayoutKind.Sequential)]
    public struct CamCtrlLED
    {

        /// int
        public int seq;

        /// int
        public int lightType;

        /// int
        public int hz;

        /// int
        public int trigType;

        /// int
        public int phase;

        /// int
        public int pulseWidth;

        /// int[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I4)]
        public int[] rev;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct CamCtrlAutoCtrl
    {

        /// int
        public int standard;

        /// int
        public int maxShut;

        /// int
        public int minShut;

        /// int
        public int maxGain;

        /// int[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)]
        public int[] gainLevel;

        /// int[6]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I4)]
        public int[] agcSelect;

        /// int[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I4)]
        public int[] rev;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct CamCtrlMannualCtrl
    {

        /// int
        public int manualShut;

        /// int
        public int mannuGainLevel;

        /// int
        public int mannualGainValue;

        /// int
        public int mannualR;

        /// int
        public int mannualGr;

        /// int
        public int mannualGb;

        /// int
        public int mannualB;

        /// int
        public int mannualRoft;

        /// int
        public int mannualGroft;

        /// int
        public int mannualGboft;

        /// int
        public int mannualBoft;

        /// int[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I4)]
        public int[] rev;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct CamCtrlImageEnhance
    {

        /// int
        public int imgSaturability;

        /// int
        public int imgContrast;

        /// int
        public int imgSharpen;

        /// int
        public int imgNoise;

        /// int
        public int imgGamma;

        /// int
        public int imgGammaEnable;

        /// int[31]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31, ArraySubType = UnmanagedType.I4)]
        public int[] rev;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct CamCtrlTrigIO
    {

        /// int
        public int trigType;

        /// int
        public int trigNum;

        /// int[2]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I4)]
        public int[] trigInter;

        /// int
        public int flashEable;

        /// int
        public int flashIndex;

        /// int[8]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I4)]
        public int[] rev;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct CamCtrlExtSync
    {

        /// int
        public int enable;

        /// int
        public int phase;

        /// int
        public int filter;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct CamCtrl
    {

        /// int
        public int enableAutoExp;

        /// int
        public int enableAutoAwb;

        /// CamCtrlAutoCtrl
        public CamCtrlAutoCtrl autoCtrl;

        /// CamCtrlMannualCtrl
        public CamCtrlMannualCtrl manualCtrl;

        /// CamCtrlImageEnhance
        public CamCtrlImageEnhance imgEnhance;

        /// CamCtrlLED[5]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.Struct)]
        public CamCtrlLED[] led;

        /// CamCtrlTrigIO[8]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.Struct)]
        public CamCtrlTrigIO[] trigIO;

        /// CamCtrlExtSync
        public CamCtrlExtSync extSync;

        /// int
        public int jpegQ;

        /// int
        public int h264W;

        /// int
        public int h264H;

        /// int
        public int h264Bitrate;

        /// int
        public int ip;

        /// int
        public int netmask;

        /// int
        public int gateway;

        /// int
        public int systime;

        /// unsigned short
        public ushort trig_shut;

        /// unsigned short
        public ushort trig_gain;

        /// int
        public int sensorType;

        /// int[126]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 126, ArraySubType = UnmanagedType.I4)]
        public int[] rev;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DayTime
    {

        /// unsigned char
        public byte startHour;

        /// unsigned char
        public byte startMinute;

        /// unsigned char
        public byte endHour;

        /// unsigned char
        public byte endMinute;
    }


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct pkg_vehicle
    {

        /// unsigned int
        public uint sequence_id;

        /// unsigned int
        public uint realtime_data;

        /// char[64]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string packet_id;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string device_id;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string addr_id;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string direction_id;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string camera_id;

        /// char[32]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string lane_id;

        /// char[96]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 96)]
        public string addr_name;

        /// char[96]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 96)]
        public string direction_name;

        /// char[16]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string plate;

        /// unsigned short
        public ushort plate_x;

        /// unsigned short
        public ushort plate_y;

        /// unsigned short
        public ushort plate_w;

        /// unsigned short
        public ushort plate_h;

        /// int
        public int plate_confidence;

        /// unsigned char
        public byte plate_color;

        /// unsigned char
        public byte vehicle_style;

        /// unsigned char
        public byte vehicle_color;

        /// unsigned char
        public byte triger_type;

        /// int
        public int redlight_begin_sec;

        /// int
        public int redlight_begin_usec;

        /// unsigned int
        public uint system_type;

        /// unsigned int
        public uint vio_type;

        /// unsigned short
        public ushort vehicle_speed;

        /// unsigned short
        public ushort limit_speed;

        /// int
        public int recoImageIndex;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] vehicle_x;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] vehicle_y;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] vehicle_w;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] vehicle_h;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] red_lamp_x;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] red_lamp_y;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] red_lamp_w;

        /// unsigned short[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U2)]
        public ushort[] red_lamp_h;

        /// unsigned short
        public ushort vio_red_lamp_index;

        /// unsigned short
        public ushort direction;

        /// char[56]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 56)]
        public string reserved;

        /// unsigned char
        public byte img_num;

        /// unsigned char
        public byte video_num;

        /// unsigned char
        public byte plate_img_num;

        /// unsigned char
        public byte face_num;

        /// unsigned int[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U4)]
        public uint[] img_len;

        /// unsigned int[2]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
        public uint[] video_len;

        /// unsigned int[2]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
        public uint[] plate_img_len;

        /// unsigned int[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.U4)]
        public uint[] face_img_len;

        /// char[8]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
        public string img_format;

        /// char[8]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
        public string video_format;

        /// char[8]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
        public string plate_img_format;

        /// char[8]
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
        public string face_img_format;

        /// int[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)]
        public int[] img_time_sec;

        /// int[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)]
        public int[] img_time_usec;

        /// int[2]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I4)]
        public int[] video_start_sec;

        /// int[2]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I4)]
        public int[] video_start_usec;

        /// int[2]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I4)]
        public int[] video_end_sec;

        /// int[2]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I4)]
        public int[] video_end_usec;

        /// unsigned short[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.U2)]
        public ushort[] face_x;

        /// unsigned short[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.U2)]
        public ushort[] face_y;

        /// unsigned short[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.U2)]
        public ushort[] face_w;

        /// unsigned short[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.U2)]
        public ushort[] face_h;

        /// unsigned char*[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.SysUInt)]
        public IntPtr[] img;

        /// unsigned char*[2]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.SysUInt)]
        public IntPtr[] video;

        /// unsigned char*[2]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.SysUInt)]
        public IntPtr[] plate_img;

        /// unsigned char*[32]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.SysUInt)]
        public IntPtr[] face_img;
    }


    #endregion


    #region callback defition
    /// Return Type: void
    ///cam: HA_Cam*
    ///ip: char*
    ///port: unsigned short
    ///event: int
    ///usrParam: int
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void HA_ConnectEventCb_t(IntPtr cam, [In] [MarshalAs(UnmanagedType.LPStr)] string ip, ushort port, int evt, int usrParam);

    /// Return Type: void
    ///cam: HA_Cam*
    ///ip: char*
    ///stream: HA_LiveStream*
    ///usrParam: int
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void HA_LiveStreamCb_t(IntPtr cam, [In] [MarshalAs(UnmanagedType.LPStr)] string ip, ref HA_LiveStream stream, int usrParam);

    /// Return Type: void
    ///cam: HA_Cam*
    ///ip: char*
    ///port: unsigned short
    ///dataType: int
    ///data: char*
    ///dataLen: unsigned int
    ///usrParam: int
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void HA_DataReadCb_t(IntPtr cam, [In] [MarshalAs(UnmanagedType.LPStr)] string ip, ushort port, int dataType, [In] IntPtr data, uint dataLen, int usrParam);

    /// Return Type: void
    ///cam: HA_Cam*
    ///rgb: unsigned char*
    ///width: int
    ///height: int
    ///usrParam: int
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void HA_DecodeImageCb_t(IntPtr cam, IntPtr rgb, int width, int height, int usrParam);




    /// Return Type: void
    ///cam: HA_Cam*
    ///index: int
    ///data: char*
    ///size: int
    ///usrParam: int
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void HA_ReadTSerialCb_t(IntPtr cam, int index, [In] IntPtr data, int size, int usrParam);


    /// Return Type: void
    ///cam: HA_Cam*
    ///index: int
    ///state: int
    ///usrParam: IntPtr
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void HA_IOStateCb_t(IntPtr cam, int index, [In] int state, IntPtr usrParam);



    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void HA_PlateInfoCb_t(IntPtr cam, IntPtr vehicle, int usrParam);

    #endregion

    public static class HaSdk
    {
        const string DllName = "libhasdk.dll";


        #region inner method definition

        [DllImport(DllName, EntryPoint = "HA_GetWhiteList", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_GetWhiteListInner(IntPtr cam, IntPtr allowList, int maxNum, ref int listNum);


        [DllImport(DllName, EntryPoint = "HA_SetWhiteList", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_SetWhiteListInner(IntPtr cam, IntPtr allowList, int listNum);


        [DllImport(DllName, EntryPoint = "HA_WriteTSerial", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_WriteTSerialInner(IntPtr cam, int index, [In] IntPtr data, int size);


        [DllImport(DllName, EntryPoint = "HA_GetCustomerSN", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_GetCustomerSNInner(IntPtr cam, IntPtr sn, ref int SNSize);

        [DllImport(DllName, EntryPoint = "HA_ReadCustomerAuthCode", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_ReadCustomerAuthCodeInner(IntPtr cam, IntPtr auth, ref int size);


        [DllImport(DllName, EntryPoint = "HA_WriteCustomerAuthCode", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_WriteCustomerAuthCodeInner(IntPtr cam, IntPtr auth, int size);


        [DllImport(DllName, EntryPoint = "HA_InsertWhiteList", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_InsertWhiteList(IntPtr cam, IntPtr wList);


        [DllImport(DllName, EntryPoint = "HA_DeleteWhiteListByPlate", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_DeleteWhiteListByPlateInner(IntPtr cam, IntPtr plate);

        [DllImport(DllName, EntryPoint = "HA_SearchWhiteListByPlate", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_SearchWhiteListByPlateInner(IntPtr cam, IntPtr plate, IntPtr wList);


        [DllImport(DllName, EntryPoint = "HA_UpdateWhiteListByPlate", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_UpdateWhiteListByPlateInner(IntPtr cam, IntPtr wList);



        #endregion



        /// Return Type: int
        [DllImport(DllName, EntryPoint = "HA_GetVersion", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_GetVersion();


        /// Return Type: void
        [DllImport(DllName, EntryPoint = "HA_Init", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_Init();


        /// Return Type: void
        [DllImport(DllName, EntryPoint = "HA_DeInit", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_DeInit();


        /// Return Type: void
        ///cb: HA_ConnectEventCb_t
        ///usrParam: int
        [DllImport(DllName, EntryPoint = "HA_RegConnectEventCb", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_RegConnectEventCb(HA_ConnectEventCb_t cb, int usrParam);


        [DllImport(DllName, EntryPoint = "HA_RegConnectEventCbEx", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_RegConnectEventCbEx(IntPtr cam, HA_ConnectEventCb_t cb, int usrParam);


        /// Return Type: void
        ///cb: HA_LiveStreamCb_t
        ///usrParam: int
        [DllImport(DllName, EntryPoint = "HA_RegLiveStreamCb", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_RegLiveStreamCb(HA_LiveStreamCb_t cb, int usrParam);


        [DllImport(DllName, EntryPoint = "HA_RegLiveStreamCbEx", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_RegLiveStreamCbEx(IntPtr cam, HA_LiveStreamCb_t cb, int usrParam);


        /// Return Type: void
        ///cb: HA_DataReadCb_t
        ///usrParam: int
        [DllImport(DllName, EntryPoint = "HA_RegDataReadCb", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_RegDataReadCb(HA_DataReadCb_t cb, int usrParam);


        [DllImport(DllName, EntryPoint = "HA_RegDataReadCbEx", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_RegDataReadCbEx(IntPtr cam, HA_DataReadCb_t cb, int usrParam);


        /// Return Type: void
        ///cb: HA_DataReadCb_t
        ///usrParam: int
        [DllImport(DllName, EntryPoint = "HA_RegIOStateCb", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_RegIOStateCb(IntPtr cam, HA_IOStateCb_t cb, IntPtr userParm);


        /// Return Type: void
        ///camType: CAM_TYPE
        [DllImport(DllName, EntryPoint = "HA_SetCamType", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_SetCamType(CAM_TYPE camType);


        /// Return Type: void
        ///charEncode: CHAR_ENCODE
        [DllImport(DllName, EntryPoint = "HA_SetCharEncode", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_SetCharEncode(CHAR_ENCODE charEncode);


        /// Return Type: int
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_Connected", CallingConvention = CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.I1)]
        public static extern bool HA_Connected(IntPtr cam);


        /*
        * @brief   连接相机
        * @param   ip[in]   相机ip
        * @param   port[in]   相机端口，固定为9527
        * @param   usrName[in]   用户名，目前版本无效，传空即可
        * @param   password[in]   密码，目前版本无效，传空即可
        * @param   errorNum[out]  连接失败错误号，，目前版本无效
        * @return  NULL 连接失败
        * @return  非NULL 连接成功
        */
        [DllImport(DllName, EntryPoint = "HA_Connect", CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr HA_Connect(
            [In]
            [MarshalAs(UnmanagedType.LPStr)]
            string ip,
            ushort port,
            [In]
            [MarshalAs(UnmanagedType.LPStr)]
            string usrName,
            [In]
            [MarshalAs(UnmanagedType.LPStr)]
            string password,
            ref int errorNum);



        [DllImport(DllName, EntryPoint = "HA_ConnectEx", CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr HA_ConnectEx(
           [In]
            [MarshalAs(UnmanagedType.LPStr)]
            string ip,
           ushort port,
           [In]
            [MarshalAs(UnmanagedType.LPStr)]
            string usrName,
           [In]
            [MarshalAs(UnmanagedType.LPStr)]
            string password,
           ref int errorNum,
           [In]
           [MarshalAs(UnmanagedType.I4)]
           int channel,
           [In]
           [MarshalAs(UnmanagedType.Bool)]
           bool autoReconnect);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_DisConnect", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_DisConnect(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        ///hWnd: void*
        [DllImport(DllName, EntryPoint = "HA_StartStream", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_StartStream(IntPtr cam, IntPtr hWnd);


        /// Return Type: void
        ///cam: HA_Cam*
        ///hWnd: void*
        ///cb: HA_DecodeImageCb_t
        ///usrParam: int
        [DllImport(DllName, EntryPoint = "HA_StartStreamEx", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_StartStreamEx(IntPtr cam, IntPtr hWnd, HA_DecodeImageCb_t cb, int usrParam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_StopStream", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_StopStream(IntPtr cam);


        /// Return Type: int
        ///cam: HA_Cam*
        ///fileName: char*
        [DllImport(DllName, EntryPoint = "HA_CapImgToFile", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_CapImgToFile(IntPtr cam, [In] [MarshalAs(UnmanagedType.LPStr)] string fileName);


        [DllImport(DllName, EntryPoint = "HA_CapImgToBuffer", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_CapImgToBufferInner(IntPtr cam, IntPtr mem, int bufferSize, ref int len);


        public static int HA_CapImgToBuffer(IntPtr cam, byte[] buffer, ref int len)
        {
            IntPtr mem = Marshal.AllocHGlobal(buffer.Length);
            int result = HA_CapImgToBufferInner(cam, mem, buffer.Length, ref len);
            if (len > 0 && len <= buffer.Length)
            {
                Marshal.Copy(mem, buffer, 0, len);
            }
            Marshal.FreeHGlobal(mem);
            return result;
        }


        /// Return Type: int
        ///cam: HA_Cam*
        ///usrParam: int
        [DllImport(DllName, EntryPoint = "HA_Trigger", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_Trigger(IntPtr cam, int usrParam);


        /// Return Type: int
        ///cam: HA_Cam*
        ///allowList: HA_AllowList*
        ///listNum: int
        public static int HA_SetWhiteList(IntPtr cam, IList<HA_AllowList> allowList)
        {
            var count = allowList.Count;
            var allowListPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HA_AllowList)) * count);

            for (int i = 0; i < count; i++)
            {
                Marshal.StructureToPtr(allowList[i], new IntPtr(allowListPtr.ToInt64() + Marshal.SizeOf(typeof(HA_AllowList)) * i), false);
            }

            int ret = HA_SetWhiteListInner(cam, allowListPtr, count);
            Marshal.FreeHGlobal(allowListPtr);
            return ret;
        }



        /// Return Type: int
        ///cam: HA_Cam*
        ///allowList: HA_AllowList*
        ///maxNum: int
        ///listNum: int*
        public static int HA_GetWhiteList(IntPtr cam, IList<HA_AllowList> allowList)
        {
            int allowNum = 2000;
            var allowListPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HA_AllowList)) * allowNum);
            int getNum = 0;

            int ret = HA_GetWhiteListInner(cam, allowListPtr, allowNum, ref getNum);

            for (int i = 0; i < getNum; i++)
            {
                var allow = (HA_AllowList)Marshal.PtrToStructure(new IntPtr(allowListPtr.ToInt64() + Marshal.SizeOf(typeof(HA_AllowList)) * i),
                    typeof(HA_AllowList));

                allowList.Add(allow);
            }

            Marshal.FreeHGlobal(allowListPtr);
            return ret;
        }


        /// Return Type: int
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_ClearWhiteList", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_ClearWhiteList(IntPtr cam);


        /// Return Type: int
        ///cam: HA_Cam*
        ///version: VERSION*
        [DllImport(DllName, EntryPoint = "HA_GetSystemVersion", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_GetSystemVersion(IntPtr cam, ref VERSION version);


        /// Return Type: int
        ///cam: HA_Cam*
        ///cfg: config_gateway*
        [DllImport(DllName, EntryPoint = "HA_GetGatewayConfig", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_GetGatewayConfig(IntPtr cam, ref config_gateway cfg);


        /// Return Type: int
        ///cam: HA_Cam*
        ///cfg: config_gateway*
        [DllImport(DllName, EntryPoint = "HA_SetGatewayConfig", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_SetGatewayConfig(IntPtr cam, ref config_gateway cfg);


        /// <summary>
        /// 获取离线工作模式
        /// </summary>
        /// <param name="cam"></param>
        /// <param name="offlineFlag">0为在线, 1为离线，2为自动（即脱机检查）</param>
        /// <returns></returns>
        [DllImport(DllName, EntryPoint = "HA_GetGatewayOfflineMode", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_GetGatewayOfflineMode(IntPtr cam, ref int offlineFlag);


        /// <summary>
        /// 设置离线工作模式
        /// </summary>
        /// <param name="cam">相机句柄</param>
        /// <param name="offlineFlag">0为在线, 1为离线，2为自动（即脱机检查）</param>
        /// <returns></returns>
        [DllImport(DllName, EntryPoint = "HA_SetGatewayOfflineMode", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_SetGatewayOfflineMode(IntPtr cam, int offlineFlag);


        /// Return Type: int
        ///cam: HA_Cam*
        ///open: int
        [DllImport(DllName, EntryPoint = "HA_SetAlarm", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_SetAlarm(IntPtr cam, int open);


        /// Return Type: int
        ///cb: HA_ReadTSerialCb_t
        ///usrParam: int
        [DllImport(DllName, EntryPoint = "HA_RegReadTSerialCb", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_RegReadTSerialCb(HA_ReadTSerialCb_t cb, int usrParam);


        [DllImport(DllName, EntryPoint = "HA_RegReadTSerialCbEx", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_RegReadTSerialCbEx(IntPtr cam, HA_ReadTSerialCb_t cb, int usrParam);


        /// Return Type: int
        ///cam: HA_Cam*
        ///index: int
        ///baudrate: int*
        ///parity: int*
        ///databit: int*
        ///stopbit: int*
        [DllImport(DllName, EntryPoint = "HA_GetTSerial", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_GetTSerial(IntPtr cam, int index, ref int baudrate, ref int parity, ref int databit, ref int stopbit);


        /// <summary>
        /// 打开串口
        /// </summary>
        /// <param name="cam">相机句柄</param>
        /// <param name="index">串口编号，从1开始，目前只支持一路串口</param>
        /// <param name="baudrate">波特率，只能为以下值：1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, 128000, 256000</param>
        /// <param name="parity">奇偶校验，0:none, 1:odd, 2:even, 3:mark, 4:space</param>
        /// <param name="databit">数据位，只能为5，6，7，8</param>
        /// <param name="stopbit">停止位，只能为1，2</param>
        /// <returns></returns>
        [DllImport(DllName, EntryPoint = "HA_OpenTSerial", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_OpenTSerial(IntPtr cam, int index, int baudrate, int parity, int databit, int stopbit);



        [DllImport(DllName, EntryPoint = "HA_EncodeJpeg", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_EncodeJpeg(IntPtr buffer, uint dwWidth, uint dwHeight, IntPtr pJpgBuffer, ref uint dwJpgSize);


        /// Return Type: int
        ///cam: HA_Cam*
        ///index: int
        ///data: char*
        ///size: int
        public static int HA_WriteTSerial(IntPtr cam, int index, byte[] data)
        {
            var ptr = Marshal.AllocHGlobal(data.Length);
            Marshal.Copy(data, 0, ptr, data.Length);
            var result = HA_WriteTSerialInner(cam, index, ptr, data.Length);
            Marshal.FreeHGlobal(ptr);
            return result;

        }


        /// Return Type: int
        ///cam: HA_Cam*
        ///index: int
        [DllImport(DllName, EntryPoint = "HA_CloseTSerial", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_CloseTSerial(IntPtr cam, int index);


        /// Return Type: int
        ///cam: HA_Cam*
        ///ctrl: CamCtrl*
        [DllImport(DllName, EntryPoint = "HA_GetCamParam", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_GetCamParam(IntPtr cam, ref CamCtrl ctrl);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_RebootCam", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_RebootCam(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_SaveCamParam", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_SaveCamParam(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        ///ctrl: CamCtrlAutoCtrl*
        [DllImport(DllName, EntryPoint = "HA_SetAutoCtrl", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_SetAutoCtrl(IntPtr cam, ref CamCtrlAutoCtrl ctrl);


        /// Return Type: void
        ///cam: HA_Cam*
        ///en: CamCtrlImageEnhance*
        [DllImport(DllName, EntryPoint = "HA_SetImageEnhance", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_SetImageEnhance(IntPtr cam, ref CamCtrlImageEnhance en);


        /// Return Type: void
        ///cam: HA_Cam*
        ///q: int
        [DllImport(DllName, EntryPoint = "HA_SetJpegQ", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_SetJpegQ(IntPtr cam, int q);


        /// Return Type: void
        ///cam: HA_Cam*
        ///w: int
        ///h: int
        ///bitrate: int
        [DllImport(DllName, EntryPoint = "HA_SetH264", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_SetH264(IntPtr cam, int w, int h, int bitrate);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_ZoomUpStart", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_ZoomUpStart(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_ZoomUpStop", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_ZoomUpStop(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_ZoomDownStart", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_ZoomDownStart(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_ZoomDownStop", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_ZoomDownStop(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_FocusUpStart", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_FocusUpStart(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_FocusUpStop", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_FocusUpStop(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_FocusDownStart", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_FocusDownStart(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_FocusDownStop", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_FocusDownStop(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_ZoomUp", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_ZoomUp(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_ZoomDown", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_ZoomDown(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_FocusUp", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_FocusUp(IntPtr cam);


        /// Return Type: void
        ///cam: HA_Cam*
        [DllImport(DllName, EntryPoint = "HA_FocusDown", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_FocusDown(IntPtr cam);


        /// Return Type: int
        ///cam: HA_Cam*
        ///sn: char*
        ///SNSize: int*

        public static int HA_GetCustomerSN(IntPtr cam, out string sn)
        {
            var size = 128;
            var ptr = Marshal.AllocHGlobal(size);
            var result = HA_GetCustomerSNInner(cam, ptr, ref size);
            sn = result == 0 ? Marshal.PtrToStringAnsi(ptr, size) : null;
            Marshal.FreeHGlobal(ptr);
            return result;
        }


        /// Return Type: int
        ///cam: HA_Cam*
        ///auth: char*
        ///size: int

        public static int HA_WriteCustomerAuthCode(IntPtr cam, string code)
        {
            var ptr = Marshal.StringToHGlobalAnsi(code);
            var result = HA_WriteCustomerAuthCodeInner(cam, ptr, code.Length);
            Marshal.FreeHGlobal(ptr);
            return result;
        }


        /// Return Type: int
        ///cam: HA_Cam*
        ///auth: char*
        ///size: int*
        public static int HA_ReadCustomerAuthCode(IntPtr cam, out string code)
        {
            var size = 1024;
            var ptr = Marshal.AllocHGlobal(size);
            var result = HA_ReadCustomerAuthCodeInner(cam, ptr, ref size);
            code = result == 0 ? Marshal.PtrToStringAnsi(ptr, size) : null;
            Marshal.FreeHGlobal(ptr);
            return result;
        }


        public static int HA_AddWhiteList(IntPtr cam, HA_AllowList item)
        {
            var size = Marshal.SizeOf(item);
            var itemPtr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(item, itemPtr, false);
            var result = HA_InsertWhiteList(cam, itemPtr);
            Marshal.FreeHGlobal(itemPtr);
            return result;
        }

        public static int HA_DeletehiteListByPlate(IntPtr cam, string plate)
        {
            var platePtr = Marshal.StringToHGlobalAnsi(plate);
            var result = HA_DeleteWhiteListByPlateInner(cam, platePtr);
            Marshal.FreeHGlobal(platePtr);
            return result;
        }


        [DllImport(DllName, EntryPoint = "HA_SetNotifyConnected", CallingConvention = CallingConvention.StdCall)]
        public static extern void HA_SetNotifyConnected(bool notify);


        [DllImport(DllName, EntryPoint = "HA_SetIOState", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_SetIOState(IntPtr cam, int index, int state);


        [DllImport(DllName, EntryPoint = "HA_SetOfflinePlateInfoCb", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_SetOfflinePlateInfoCb(IntPtr cam, HA_PlateInfoCb_t cb, int usrParam);

        [DllImport(DllName, EntryPoint = "HA_SetQueryPlateInfoCb", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_SetQueryPlateInfoCb(IntPtr cam, HA_PlateInfoCb_t cb, int usrParam);


        [DllImport(DllName, EntryPoint = "HA_SetAlarmAuto", CallingConvention = CallingConvention.StdCall)]
        public static extern int SetIOOutputAuto(IntPtr cam, int index, int duratrionMilliSecond);


        [DllImport(DllName, EntryPoint = "HA_PlayAudio", CallingConvention = CallingConvention.StdCall)]
        public static extern int PlayAudio(IntPtr cam, IntPtr mem, int memLen);


        [DllImport(DllName, EntryPoint = "HA_GetSysTimeEx", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_GetSysTimeEx(IntPtr cam, ref int year, ref int month, ref int day, ref int hour, ref int minute, ref int second);


        [DllImport(DllName, EntryPoint = "HA_SetSysTimeEx", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_SetSysTimeEx(IntPtr cam, int year, int month, int day, int hour, int minute, int second);


        [DllImport(DllName, EntryPoint = "HA_ClearAllCallbacks", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_ClearAllCallbacks(IntPtr cam);


        [DllImport(DllName, EntryPoint = "HA_QueryOfflineCountByTime", CallingConvention = CallingConvention.StdCall)]
        private static extern int HA_QueryOfflineCountByTimeInner(IntPtr cam, IntPtr pStartTime, IntPtr pEndTime);


        [DllImport(DllName, EntryPoint = "HA_SaveRealDate", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_SaveRealDate(IntPtr cam, string fullPathToFile);


        [DllImport(DllName, EntryPoint = "HA_StopSaveRealDate", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_StopSaveRealDate(IntPtr cam);


        /// <summary>
        /// 根据车牌号和时间查询记录数量
        /// </summary>
        /// <param name="cam">相机句柄</param>
        /// <param name="startTime">起始时间，格式如"2015-01-02 12:20:30"</param>
        /// <param name="endTime">结束时间，格式如"2015-01-02 12:20:30"</param>
        /// <param name="keyword">车牌号关键字, 如"川A"</param>
        /// <returns></returns>
        [DllImport(DllName, EntryPoint = "HA_QueryCountByTimeAndPlate", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_QueryCountByTimeAndPlate(IntPtr cam, string startTime, string endTime, string keyword);


        /// <summary>
        /// 根据车牌号和时间查询记录
        /// </summary>
        /// <param name="cam">相机句柄</param>
        /// <param name="startTime">起始时间，格式如"2015-01-02 12:20:30"</param>
        /// <param name="endTime">结束时间，格式如"2015-01-03 12:20:30"</param>
        /// <param name="keyword">车牌号关键字, 如"川A"</param>
        /// <returns></returns>
        [DllImport(DllName, EntryPoint = "HA_QueryRecordByTimeAndPlate", CallingConvention = CallingConvention.StdCall)]
        public static extern int HA_QueryRecordByTimeAndPlate(IntPtr cam, string startTime, string endTime, string keyword);


        public static int HA_QueryOfflineCountByTime(IntPtr cam, DateTime from, DateTime to)
        {
            var start = from.ToString("yyyy-MM-dd HH:mm:ss");
            var stop = to.ToString("yyyy-MM-dd HH:mm:ss");
            var startPtr = Marshal.StringToHGlobalAnsi(start);
            var stopPtr = Marshal.StringToHGlobalAnsi(stop);
            var result = HA_QueryOfflineCountByTimeInner(cam, startPtr, stopPtr);
            Marshal.FreeHGlobal(startPtr);
            Marshal.FreeHGlobal(stopPtr);

            return result;
        }

        /// <summary>
        /// 根据车牌号搜索白名单
        /// </summary>
        /// <param name="cam">相机句柄</param>
        /// <param name="plate">完整车牌号，不支持模糊匹配</param>
        /// <param name="wList">返回搜索到的白名单</param>
        /// <returns>0: 成功， 小于0: 失败</returns>
        public static int HA_SearchWhiteListByPlate(IntPtr cam, string plate, out HA_AllowList wList)
        {
            var ptrPlate = Marshal.StringToHGlobalAnsi(plate);
            var ptrWList = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HA_AllowList)));
            var res = HA_SearchWhiteListByPlateInner(cam, ptrPlate, ptrWList);
            if (res == 0)
            {
                object obj = Marshal.PtrToStructure(ptrWList, typeof(HA_AllowList));
                wList = (HA_AllowList)obj;
            }
            else
            {

                wList = new HA_AllowList();
            }

            Marshal.FreeHGlobal(ptrPlate);
            Marshal.FreeHGlobal(ptrWList);
            return res;
        }


        public static int HA_UpdateWhiteListByPlate(IntPtr cam, HA_AllowList wList)
        {
            var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HA_AllowList)));
            Marshal.StructureToPtr(wList, ptr, false);
            var res = HA_UpdateWhiteListByPlateInner(cam, ptr);
            Marshal.FreeHGlobal(ptr);
            return res;

        }


    }
}